import 'dart:convert';
import 'dart:io';

import 'package:hex/hex.dart';
import 'package:http/http.dart' as http;
import 'package:lib_database/lib_database.dart';
import 'package:lib_util/utils/utils.dart';

class TronWeb3 {
  // 获取 tron 区块高度
  static Future<int> getBlockHeightByRpc(String rpc) async {
    try {
      var rpcUrl = "$rpc${rpc.endsWith('/jsonrpc') ? '' : '/jsonrpc'}";
      var response = await TronWeb3.createRpcRequest(rpc: rpcUrl, body: {
        "jsonrpc": "2.0",
        "method": "eth_blockNumber",
        "params": [],
        "id": 64
      });
      BigInt blockHeight = BigInt.parse(
          Utils.ensureRemoveHexPrefix(response['result']),
          radix: 16);
      return blockHeight.toInt();
    } catch (e) {
      print('TronWeb3 getBlockHeightByRpc: $e');
      return 0;
    }
  }

  // 获取 主 币 余额  存在 精度问题
  static Future<String> getMainTokenBalance(String rpc, String userAddress,
      {int decimal = 6}) async {
    try {
      var rpcUrl = "$rpc${rpc.endsWith('/jsonrpc') ? '' : '/jsonrpc'}";
      var address = "0x${Utils.convertTronAddressFromBase58ToHex(userAddress)}";
      var response = await TronWeb3.createRpcRequest(rpc: rpcUrl, body: {
        "jsonrpc": "2.0",
        "method": "eth_getBalance",
        "params": [address, "latest"],
        "id": 65
      });

      BigInt balance = BigInt.parse(
          Utils.ensureRemoveHexPrefix(response['result']),
          radix: 16);

      if (balance.toString() == '0') {
        return '0';
      }

      return double.parse(Utils.formatStringBalance(
              (BigInt.parse(balance.toString()) / BigInt.from(10).pow(decimal))
                  .toString(),
              fractionDigits: Config.balanceFixedNum))
          .toString();
    } catch (_) {
      return '0';
    }
  }

  // 获取 主 币 余额  存在 精度问题
  static Future<String> getTokenBalance(String rpc, String tokenAddress,String userAddress,
      {int decimal = 6}) async {
    try {
      var rpcUrl = "${rpc.endsWith('/jsonrpc') ? rpc.split('/jsonrpc')[0] : rpc}/wallet/triggerconstantcontract";
      var toAddress = "41${Utils.convertTronAddressFromBase58ToHex(userAddress)}";
      var contractAddress = "41${Utils.convertTronAddressFromBase58ToHex(tokenAddress)}";
      var response = await TronWeb3.createRpcRequest(rpc: rpcUrl, body: {
        "contract_address": contractAddress,
        "function_selector":"balanceOf(address)",
        "parameter":"0000000000000000000000${toAddress}",
        "owner_address": toAddress
      });

      BigInt balance = BigInt.parse(
          Utils.ensureRemoveHexPrefix(response['constant_result'][0]),
          radix: 16);
      if (balance.toString() == '0') {
        return '0.00';
      }
      return double.parse(Utils.formatStringBalance(
              (BigInt.parse(balance.toString()) / BigInt.from(10).pow(decimal))
                  .toString(),
              fractionDigits: Config.balanceFixedNum))
          .toString();
    } catch (_) {
      return '0.00';
    }
  }

  // 获取 币种信息  chainId, contractAddress, rpc
  static Future<Map<String, dynamic>?> getERC20TokenInfoByRpc(String rpc,{
    required String tokenAddress,
    required String userAddress
  }) async {
    try {
      var domain = "${rpc.endsWith('/jsonrpc') ? rpc.split('/jsonrpc')[0] : rpc}";
      // 获取 代币合约的 abi  没有 abi 的 非代币
      var toAddress = "41${Utils.convertTronAddressFromBase58ToHex(userAddress)}";
      var contractAddress = "41${Utils.convertTronAddressFromBase58ToHex(tokenAddress)}";
      var responseName = await TronWeb3.createRpcRequest(rpc: domain+'/wallet/triggerconstantcontract', body: {
        "owner_address":  toAddress,
        "contract_address": contractAddress,
        "function_selector": "name()",
      });
      var responseSymbol = await TronWeb3.createRpcRequest(rpc: domain+'/wallet/triggerconstantcontract', body: {
        "owner_address":  toAddress,
        "contract_address": contractAddress,
        "function_selector": "symbol()",
      });

      var responseDecimals = await TronWeb3.createRpcRequest(rpc: domain+'/wallet/triggerconstantcontract', body: {
        "owner_address":  toAddress,
        "contract_address": contractAddress,
        "function_selector": "decimals()",
      });
      BigInt decimals = BigInt.parse(
          Utils.ensureRemoveHexPrefix(responseDecimals['constant_result'][0]),
          radix: 16);
      return {
        "chainId": '728126428',
        "address": tokenAddress,
        "name": TronWeb3.decodeParams(responseName['constant_result'][0]),
        "decimals": decimals.toInt(),
        "symbol": TronWeb3.decodeParams(responseSymbol['constant_result'][0]),
      };
    } catch (e) {
      print('e $e');
      return null;
    }
  }

  // 结构 波长 返回的参数
  static decodeParams(String data){
    try{
      // final double noi = 32;
      List<int> bytes = HEX.decode(data);
      // final double cycles= bytes.length / noi;
      // 解析参数值编码
      List<int> firstArgValueBytes = bytes.sublist(64, 96);
      // List<int> secondArgValueBytes = bytes.sublist(96, 128);

      // 将字节数组转换为字符串
      // String firstArgValue = ;
      return String.fromCharCodes(firstArgValueBytes);
    }catch(e){
      throw Exception('Tron error： analysis returns abnormal data ::::::::$e');
    }
  }


  // 获取 gas 费
  static Future<Map<String, dynamic>?> getErc20Gas(rpc, transaction,
      {int decimal = 6}) async {
    try {
      var rpcUrl = "$rpc${rpc.endsWith('/jsonrpc') ? '' : '/jsonrpc'}";
      var response = await TronWeb3.createRpcRequest(rpc: rpcUrl, body: {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "eth_gasPrice",
        "params": []
      });
      BigInt gasPrice = BigInt.parse(
          Utils.ensureRemoveHexPrefix(response['result']),
          radix: 16);
      final gas = Utils.formatStringBalance(
          (BigInt.parse(gasPrice.toString()) / BigInt.from(10).pow(decimal))
              .toString(),
          fractionDigits: Config.balanceFixedNum);
      final adjustedGas = double.parse(gas).toString();
      return {
        'gasPrice': gasPrice,
        'gas': adjustedGas,
        "adjustedGas": adjustedGas
      };
    } catch (e) {
      print('getErc20Gas $e');
      return null;
    }
  }


  static Future<Map<String, dynamic>?> getWeb3SignTx(
      rpcUrl, int chainId, Map<String, dynamic> tran, tokenAddress, type) async {
    try{
      return {'1':'1'};
    }catch(e){
      throw Exception(e);
    }
  }

  static Future<Map<String, dynamic>> createRpcRequest(
      {required String rpc, required Map<String, dynamic> body}) async {
    http.Response resp = await http.post(Uri.parse(rpc),
        headers: {
          HttpHeaders.contentTypeHeader: 'application/json',
          HttpHeaders.acceptHeader: "application/json",
          // timmy 私人的  会限制速率
          "TRON-PRO-API-KEY": "8b2590ef-9176-4523-9da8-ff9a94091bee"
        },
        body: json.encode(body));
    if (resp.statusCode == 308) {
      //post 重定向
      resp = await http.post(Uri.parse(resp.headers["location"]!),
          headers: {
            HttpHeaders.contentTypeHeader: 'application/json',
            HttpHeaders.acceptHeader: "application/json"
          },
          body: json.encode(body));
    }
    String result = utf8.decode(resp.bodyBytes);
    Config.logger.d('rpc request:\n${json.encode(body)}\nresponse:\n$result');
    // Config.logger.d('rpc:$rpc\nrpc request:\n${json.encode(body)}\nresponse:\n$result');
    Map<String, dynamic> map = json.decode(result);
    return map;
  }
}
